package tests.user;

import tester.*;

import java.util.*;
import java.math.*;

/**
 * Copyright 2007, 2008 Viera K. Proulx
 * This program is distributed under the terms of the 
 * GNU Lesser General Public License (LGPL)
 */

/**
 * A class to demonstrate and test the use of the tester library 
 * for data of primitive types, numerical types, and the wrapper classes
 * for primitive types.
 *  
 * @author Viera K. Proulx
 * @since 20 March 2008, 11 November 2008
 *
 */
@Example
public class ExamplesPrimitive{
  
  ExamplesPrimitive(){}
 
  //---- Examples and Tests for all primitive types and wrapper classes ----//
  /** Sample data: Primitive types */
  public int int1 = 1;
  public int int2 = 2;
  public short short1 = 1;
  public short short2 = 2;
  public short short1a = 1;
  public long long1 = 1;
  public long long2 = 2;
  public long long1a = 1;
  public byte byte1 = 1;
  public byte byte2 = 2;
  public byte byte1a = 1;
  public boolean bool1 = true;
  public boolean bool2 = false;
  public boolean bool1a = true;
  public char charA = 'A';
  public char charB = 'B';
 
  /** sample method: int method(int) */
  public int nPlus5(int n){
    return n + 5;
  }

  /**
   * <p>Tests for all primitive data types:</p>
   * <p>    test the same method for the type - result true</p>
   * <p>    test the same method for the type - result false</p>
   * <p>    test the checExpect for the type</p>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testPrimitive(Tester t){
  	return
    // int test 
    t.checkExpect(t.same(int1, int2), false, 
    		"primitive - int same - different") &&
    t.checkExpect(t.same(int1, 1), true, 
    		"primitive - int same - same") &&
    t.checkExpect(nPlus5(5), 10, 
    		"primitive - int - check") &&
    		
    // short test
    t.checkExpect(t.same(short1, short2), false, 
    		"primitive - short - different") &&
    t.checkExpect(t.same(short1, short1a), true, 
    		"primitive - short - same") &&
    t.checkExpect(short1, short1a, "" +
    		"primitive - short - check") &&
    		
    // long test
    t.checkExpect(t.same(long1, long2), false, 
    		"primitive - long - different") &&
    t.checkExpect(t.same(long1, long1a), true, 
    		"primitive - long - same") &&
    t.checkExpect(long1, long1a, 
    		"primitive - long - check") &&
    		
    // byte test
    t.checkExpect(t.same(byte1, byte2), false, 
    		"primitive - byte - different") &&
    t.checkExpect(t.same(byte1, byte1a), true, 
    		"primitive - byte - same") &&
    t.checkExpect(byte1, byte1a, 
    		"primitive - byte - check") &&
    		
    // boolean test
    t.checkExpect(t.same(bool1, bool2), false, 
    		"primitive - boolean - different") &&
    t.checkExpect(t.same(bool1, bool1a), true, 
    		"primitive - boolean - same") &&
    t.checkExpect(bool1, bool1a, 
    		"primitive - boolean - check") &&
    		
    // char test
    t.checkExpect(t.same(charA, charB), false, 
    		"primitive - char - different") &&
    t.checkExpect(t.same(charA, 'A'), true, 
    		"primitive - char - same") &&
    t.checkExpect(charA, 'A', 
    		"primitive - char - check") &&
    // final test that fails
    		
    t.checkFail(charA, charB, 
    		"primitive - char - different - fails");
  }
  
  /**
   * Tests for the checkRange for all primitive types and for 
   * <code>String</code>
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   * @return true
   */
  @TestMethod
  public boolean testPrimitiveRange(Tester t){
  	// int test 
    t.checkRange(3, 3, 5, "[3 <= 3 < 5)");
    t.checkRange(4, 3, 5, "[2 <= 4 < 5)");
    //t.checkRange(-2, 3, 5, "Fails: [2 <= -2 < 5)");
    //t.checkRange(5, 3, 5, "Fails: [2 <= 5 < 5)");
    //t.checkRange(8, 3, 5, "Fails: [2 <= 8 < 5)");
    
    // short test
    short sminus2 = (short)-2;
    short s3 = (short)3;
    short s4 = (short)4;
    short s5 = (short)5;
    short s8 = (short)8;
    t.checkRange(s3, s3, s5, "short: [3 <= 3 < 5)");
    t.checkRange(s4, s3, s5, "short: [2 <= 4 < 5)");
    //t.checkRange(sminus2, s3, s5, "Fails short: [2 <= -2 < 5)");
    //t.checkRange(s5, s3, s5, "Fails short: [2 <= 5 < 5)");
    //t.checkRange(s8, s3, s5, "Fails short: [2 <= 8 < 5)"); 
    
    // long test
    long lminus2 = (long)-2;
    long l3 = (long)3;
    long l4 = (long)4;
    long l5 = (long)5;
    long l8 = (long)8;
    t.checkRange(l3, l3, l5, "long: [3 <= 3 < 5)");
    t.checkRange(l4, l3, l5, "long: [2 <= 4 < 5)");
    //t.checkRange(lminus2, l3, l5, "Fails long: [2 <= -2 < 5)");
    //t.checkRange(l5, l3, l5, "Fails long: [2 <= 5 < 5)");
    //t.checkRange(l8, l3, l5, "Fails long: [2 <= 8 < 5)"); 
    
    // byte test
    byte bminus2 = (byte)-2;
    byte b3 = (byte)3;
    byte b4 = (byte)4;
    byte b5 = (byte)5;
    byte b8 = (byte)8;
    t.checkRange(b3, b3, b5, "byte: [3 <= 3 < 5)");
    t.checkRange(b4, b3, b5, "byte: [2 <= 4 < 5)");
    //t.checkRange(bminus2, b3, b5, "Fails byte: [2 <= -2 < 5)");
    //t.checkRange(b5, b3, b5, "Fails byte: [2 <= 5 < 5)");
    //t.checkRange(b8, b3, b5, "Fails byte: [2 <= 8 < 5)"); 
    
    // boolean test
    boolean btrue = true;
    boolean bfalse = false;   
    t.checkRange(false, bfalse, btrue, "boolean: [false <= false < true)");
   //t.checkRange(true, bfalse, btrue, "Fails boolean: [false <= true < true)");
    
    // char test
    char m = 'm';
    char p1 = 'p';
    char p2 = 'p';
    char q = 'q';
    char r1 = 'r';
    char r2 = 'r';
    char s = 's';
    //t.checkRange(m, p2, r1, "Fails char: [p <= m < r)");
    t.checkRange(p1, p2, r1, "char: [p <= p < r)");
    t.checkRange(q, p2, r1, "char: [p <= q < r)");
    //t.checkRange(r2, p2, r1, "Fails char: [p <= r < r)");
    //t.checkRange(s, p2, r1, "Fails char: [p <= s < r)");
    
    // float test
    float fminus2 = (float)-2.0;
    float f3 = (float)3.0;
    float f4 = (float)4.0;
    float f5 = (float)5.0;
    float f8 = (float)8.0;
    t.checkRange(f3, f3, f5, "float: [3 <= 3 < 5)");
    t.checkRange(f4, f3, f5, "float: [2 <= 4 < 5)");
    //t.checkRange(fminus2, f3, f5, "Fails float: [2 <= -2 < 5)");
    //t.checkRange(f5, f3, f5, "Fails float: [2 <= 5 < 5)");
    //t.checkRange(f8, f3, f5, "Fails float: [2 <= 8 < 5)"); 
    
    // double test
    double dminus2 = (double)-2.0;
    double d3 = (double)3.0;
    double d4 = (double)4.0;
    double d5 = (double)5.0;
    double d8 = (double)8.0;
    t.checkRange(d3, d3, d5, "double: [3 <= 3 < 5)");
    t.checkRange(d4, d3, d5, "double: [2 <= 4 < 5)");
    //t.checkRange(dminus2, d3, d5, "Fails double: [2 <= -2 < 5)");
    //t.checkRange(d5, d3, d5, "Fails double: [2 <= 5 < 5)");
    //t.checkRange(d8, d3, d5, "Fails double: [2 <= 8 < 5)"); 
    
    // String test
    String aaa = "aaa";
    String abc1 = "abc";
    String abc2 = "abc";
    String bcd = "bcd";
    String cde = "cde";
    String cde2 = "cde";
    String def = "def";
    //t.checkRange(aaa, abc1, cde, "Fails String: [abc <= aaa < cde)");
    t.checkRange(abc2, abc1, cde, "String: [abc <= abc < cde)");
    t.checkRange(bcd, abc1, cde, "String: [abc <= bcd < cde)");
    //t.checkRange(cde, abc1, cde2, "Fails String: [abc <= cde < cde)");
    //t.checkRange(def, abc1, cde, "Fails String: [abc <= def < cde)");
    
    // inline Comparator test
    Book p = new Book("Pearl", null, 1930);
    Book c = new Book("Cosmos", null, 1960);
    Book h = new Book("Hamlet", null, 1600);

     t.checkRange(h, c, p, 
                         new Comparator<Book>(){
                         public int compare(Book b1, Book b2){
                             return b1.title.compareTo(b2.title);
                         }}, "Hamlet between Cosmos and Pearl");

    return true;
  }
  
  /** Sample data: Wrapper classes */
  public Integer wint1 = 1;
  public Integer wint2 = 2;
  public Short wshort1 = 1;
  public Short wshort2 = 2;
  public Long wlong1 = new Long("12345678901");
  public Long wlong2 = new Long("12345678902");
  public Byte wbyte1 = 1;
  public Byte wbyte2 = 2;
  public Boolean wbool1 = true;
  public Boolean wbool2 = false;
  public Boolean wbool1a = true;
  public Character wcharA = 'A';
  public Character wcharB = 'B';
 
  /**
   * <p>Tests for all wrapper data types:</p>
   * <p>    test the same method for the type - result true</p>
   * <p>    test the same method for the type - result false</p>
   * <p>    test the checExpect for the type</p>
   * 
  * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */ 
  @TestMethod
  public boolean testWrapper(Tester t){
    return
    // Integer tests
    t.checkExpect(int1, wint1, 
    		"int - Integer - same") &&
    t.checkExpect(t.same(wint1, wint2), false, 
    		"wrapper - Integer - different") &&
    t.checkExpect(t.same(wint1, new Integer(1)), true, 
    		"wrapper - Integer - same") &&
    t.checkExpect(wint1, new Integer(1), 
    		"wrapper - Integer - check") &&
    		
    // Short tests
    t.checkExpect(t.same(wshort1, wshort2), false, 
    		"wrapper - Short - different") &&
    t.checkExpect(t.same(wshort1, new Short("1")), true, 
    		"wrapper - Short - same") &&
    t.checkExpect(wshort1, new Short("1"), 
    		"wrapper - Short - check") &&
    		
    // Long tests
    t.checkExpect(t.same(wlong1, wlong2), false, 
    		"wrapper - Long - different") &&
    t.checkExpect(t.same(wlong1, new Long("12345678901")), true, 
    		"wrapper - Long - same") &&
    t.checkExpect(wlong1, new Long("12345678901"), 
    		"wrapper - Long - check") &&
    		
    // Byte tests
    t.checkExpect(t.same(wbyte1, wbyte2), false, 
    		"wrapper - Byte - different") &&
    t.checkExpect(t.same(wbyte1, new Byte("1")), true, 
    		"wrapper - Byte - same") &&
    t.checkExpect(wbyte1, new Byte("1"), 
    		"wrapper - Byte - same") &&
    		
    // Boolean tests
    t.checkExpect(t.same(wbool1, wbool2), false, 
    		"wrapper - Boolean - different") &&
    t.checkExpect(t.same(wbool1, wbool1a), true, 
    		"wrapper - Boolean - same") &&
    t.checkExpect(wbool1, wbool1a, 
    		"wrapper - Boolean - check") &&
    		
    // Char tests
    t.checkExpect(t.same(wcharA, wcharB), false, 
    		"wrapper - Character - different") &&
    t.checkExpect(t.same(wcharA, new Character('A')), true, 
    		"wrapper - Character - same") &&
    t.checkExpect(wcharA, new Character('A'), 
    		"wrapper - Character - check");
    // Final test that will fail
    /*t.checkExpect(wcharA, wcharB, 
    		"wrapper - Character - different");*/
  }
  
  /** Sample data: additional Number classes */
  public BigInteger bigint1 = new BigInteger("12345678901");
  public BigInteger bigint1a = new BigInteger("12345678901");
  public BigInteger bigint2 = new BigInteger("12345678902");
  public BigDecimal bigdec1 = new BigDecimal("1234567890.12345678901");
  public BigDecimal bigdec1a = new BigDecimal("1234567890.12345678901");
  public BigDecimal bigdec2 = new BigDecimal("1234567890.12345678902");
 
  /**
   * <p>Tests for data types that represent big numerical values:</p>
   * <p>    test the same method for the type - result true</p>
   * <p>    test the same method for the type - result false</p>
   * <p>    test the checExpect for the type</p>

   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testBigNumbers(Tester t){
    return
    // Tests for BigInteger
    t.checkExpect(t.same(bigint1, bigint2), false, 
    		"big integer - different") &&
    t.checkExpect(t.same(bigint1, bigint1a), true, 
    		"big integer - same") &&
    t.checkExpect(bigint1, bigint1a, 
    		"big integer - check") &&
    		
    // Tests for BigDecimal
    t.checkExpect(t.same(bigdec1, bigdec2), false, 
    		"big decimal - different") &&
    t.checkExpect(t.same(bigdec1, bigdec1a), true, 
    		"big decimal - same") &&
    t.checkExpect(bigdec1, bigdec1a, 
    		"big decimal - same");
  }
  
  /**
   * <p>Tests for the range check for data types that represent 
   * big numerical values:</p>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   * @return true
   */
  @TestMethod
  public boolean testBigNumbersRange(Tester t){

    BigInteger bigint0 = new BigInteger("12345678890");
    BigInteger bigint1 = new BigInteger("12345678901");
    BigInteger bigint1a = new BigInteger("12345678901");
    BigInteger bigint2 = new BigInteger("12345678902");
    BigInteger bigint3 = new BigInteger("12345678903");
    BigInteger bigint3a = new BigInteger("12345678903");
    BigInteger bigint4 = new BigInteger("12345678904");
    
  	t.checkRange(bigint1a, bigint1, bigint3, "BigInteger: [1 <= 1 < 3)");
  	t.checkRange(bigint2, bigint1, bigint3, "BigInteger: [1 <= 2 < 3)");
  	//t.checkRange(bigint0, bigint1, bigint3, "Fails BigInteger: [1 <= 0 < 3)");
  	//t.checkRange(bigint3a, bigint1, bigint3, "Fails BigInteger: [1 <= 3 < 3)");
  	//t.checkRange(bigint4, bigint1, bigint3, "Fails BigInteger: [1 <= 4 < 3)");

  	
    BigDecimal bigdec0 = new BigDecimal("1234567890.12345678900");
    BigDecimal bigdec1 = new BigDecimal("1234567890.12345678901");
    BigDecimal bigdec1a = new BigDecimal("1234567890.12345678901");
    BigDecimal bigdec2 = new BigDecimal("1234567890.12345678902");
    BigDecimal bigdec3 = new BigDecimal("1234567890.12345678903");
    BigDecimal bigdec3a = new BigDecimal("1234567890.12345678903");
    BigDecimal bigdec4 = new BigDecimal("1234567890.12345678904");
    
   	t.checkRange(bigdec1a, bigdec1, bigdec3, "BigDecimal: [1 <= 1 < 3)");
  	t.checkRange(bigdec2, bigdec1, bigdec3, "BigDecimal: [1 <= 2 < 3)");
  	//t.checkRange(bigdec0, bigdec1, bigdec3, "Fails BigDecimal: [1 <= 0 < 3)");
  	//t.checkRange(bigdec3a, bigdec1, bigdec3, "Fails BigDecimal: [1 <= 3 < 3)");
  	//t.checkRange(bigdec4, bigdec1, bigdec3, "Fails BigDecimal: [1 <= 4 < 3)");
   
  	return true;
  }
  
  //---------------- Examples and Tests for inexact numbers ---------------//

  /** Sample data: Cartesian points -- using all inexact data types */
  public CartPt pt1 = new CartPt(4.0, 3.0);
  public CartPt pt1a = new CartPt(4.0, 3.0);
  public CartPt pt2 = new CartPt(100.001, 0.0);
  public CartPtD pt1D = new CartPtD((Double)4.0, (Double)3.0);
  public CartPtD pt2D = new CartPtD((Double)100.001, (Double)0.0);
  public CartPtF pt1F = new CartPtF(new Float(4.0), new Float(3.0));
  public CartPtF pt2F = new CartPtF(new Float(100.001), new Float(0.0));
  public CartPtfloat pt1float = 
    new CartPtfloat(((Double)4.0).floatValue(), ((Double)3.0).floatValue());
  public CartPtfloat pt2float = 
    new CartPtfloat(((Double)100.001).floatValue(), 
                    ((Double)0.0).floatValue());

  /**
   * Test the comparisons for inexact numbers of the types
   * <code>double</code>
   *
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testDoubles(Tester t){
    return
    /** test double-s */
    t.checkExpect(pt1.distTo0(), 5.0, "Distance to 0 - double - test1: ") &&
    t.checkExpect(pt2.distTo0(), 100.0, "Distance to 0 - double - test2: ");
  }
  
  @TestMethod
  public boolean testDoubleFields(Tester t){
  	return 
  	t.checkExpect(pt1, pt1a, "Compare CartPt-s") &&
  	t.checkFail(pt1, pt2, "Compare CartPt-s: fail");
  }

  /**
   * Test the comparisons for inexact numbers of the types
   * <code>double</code> -- setting the tolerance too low
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance1(Tester t){
    /** make the tolerance too low */
    return
    t.setTolerance(0.0000001) &&
    t.checkExpect(t.same(pt2.distTo0(), 100.0), false, 
    		"Distance to 0 - double - low tolerance: ");
  }

  /**
   * Test the comparisons for inexact numbers of the types
   * <code>Double</code>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance2(Tester t){
   /** reset the tolerance -- test Double-s */
    return
    t.setTolerance(0.01) &&
    t.checkExpect(pt1D.distTo0(), 5.0, "Distance to 0 - Double - test1: ") &&
    t.checkExpect(pt2D.distTo0(), 100.0, "Distance to 0 - Double - test2: ");
  }
  
  /**
   * Test the comparisons for inexact numbers of the types
   * <code>Double</code> setting the tolerance too low
   *
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance3(Tester t){
    /** make the tolerance too low */
    return
    t.setTolerance(0.0000001) &&
    t.checkExpect(t.same(pt2D.distTo0(), 100.0), false, 
    		"Distance to 0 - Double - low tolerance: ");
  }
    
  /**
   * Test the comparisons for inexact numbers of the types 
   * <code>float</code>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance4(Tester t){
    /** reset the tolerance -- test float-s */
    return
    t.setTolerance(0.01) &&
    t.checkExpect(pt1float.distTo0(), 5.0, 
    		"Distance to 0 - float test1: ") &&
    t.checkExpect(pt2float.distTo0(), 100.0, 
    		"Distance to 0 - float - test2: ");
  }
  
  /**
   * Test the comparisons for inexact numbers of the types
   * <code>float</code> setting the tolerance too low
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance5(Tester t){
    /** make the tolerance too low */
    return
    t.setTolerance(0.0000001) &&
    t.checkExpect(t.same(pt2float.distTo0(), 100.0), false, 
    		"Distance to 0 - float - low tolerance: ");
  }
  
  /**
   * Test the comparisons for inexact numbers of the types
   * <code>Float</code>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance6(Tester t){
    
    /** reset the tolerance -- test Float-s */
    return
    t.setTolerance(0.01) &&
    t.checkExpect(pt1F.distTo0(), 5.0, 
    		"Distance to 0 - Float test1: ") &&
    t.checkExpect(pt2F.distTo0(), 100.0, 
    		"Distance to 0 - Float test2: ");
  }
  
  /**
   * Test the comparisons for inexact numbers of the types
   * <code>Float</code> setting the tolerance too low
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testTolerance7(Tester t){
    /** make the tolerance too low */
    return
    t.setTolerance(0.0000001) &&
    t.checkExpect(t.same(pt2F.distTo0(), 100.0), false, 
    		"Distance to 0 - Float - low tolerance: ");
  }
  
  Person jon20 = new Person("Jon", 20);
  Person dan20 = new Person("Dan", 20);
  Person ann10 = new Person("Ann", 10);
  Person ken40 = new Person("Ken", 40);
  Person dan40 = new Person("Dan", 40);
  Person kim30 = new Person("Kim", 30);
  Person pat60 = new Person("Pat", 60);
  
  Comparator<Person> comp = new PersonComparator();

  /**
   * Test the range checking of <CODE>{@link Person Person}</CODE> data
   * using its implementation of <code>Comparable</code>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testRange(Tester t){
  	//t.checkRange(ann10, jon20, ken40, "Range: below the lower bound");
  	t.checkRange(jon20, jon20, ken40, "Range: hits the lower bound");
  	t.checkRange(kim30, jon20, ken40, "Range: within the bounds");
  	//t.checkRange(dan40, jon20, ken40, "Range: hits the upper bound");
  	//t.checkRange(pat60, jon20, ken40, "Range: over the upper bound"); 	
  	return true;
  }
  
  /**
   * Test the range checking of <CODE>{@link Person Person}</CODE> data
   * using the given <code>Comparator</code>
   * 
   * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
   */
  @TestMethod
  public boolean testRangeComp(Tester t){
  	/*t.checkRange(ann10, jon20, ken40, comp, 
  			"Range comp: below the lower bound");*/
  	t.checkRange(jon20, jon20, ken40, comp, 
  			"Range comp: hits the lower bound");
  	t.checkRange(kim30, jon20, ken40, comp, 
  			"Range comp: within the bounds");
  	/*t.checkRange(dan40, jon20, ken40, comp, 
  			"Range comp: hits upper the bound");*/
  	/*t.checkRange(pat60, jon20, ken40, comp, 
  			"Range comp: over the upper bound");*/ 	
  	return true;
  }
  
  /**
   * <P>Display all data defined in the <CODE>{@link Examples Examples}</CODE> 
   * class.</P>
   * <P>Run all tests defined in the <CODE>{@link Examples Examples}</CODE> 
   * class.</P>
   */
  public static void main(String[] argv){
    ExamplesPrimitive e = new ExamplesPrimitive();

    System.out.println(
    		"\n\n---------------------------------------------------");
    System.out.println("Invoke tester.runTests(this):");
    
    //e.go();
    Tester.runReport(e, true, true);
  }
}